/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */

#ifndef _MICRO_ECC_H_
#define _MICRO_ECC_H_

#include "log.h"
#include "hash.h"
#include "ql_error_type.h"
#include "ql_type.h"

// secp256k1 byte length, [DO NOT MODIFY!]
#define uECC_BYTES      32
// ----------------------------------------------
// Platform selection options.
// If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
// ----------------------------------------------
#define uECC_arch_other 0
#define uECC_x86        1
#define uECC_x86_64     2
#define uECC_arm        3
#define uECC_arm_thumb  4
#define uECC_avr        5
#define uECC_arm_thumb2 6

// ----------------------------------------------
// Inline assembly options.
// ----------------------------------------------
#define uECC_asm_none   0    // Use standard C99 only
#define uECC_asm_small  1    // Use GCC inline assembly for the target platform (if available), optimized for minimum size
#define uECC_asm_fast   2    // Use GCC inline assembly optimized for maximum speed
#ifndef uECC_ASM
#define uECC_ASM uECC_asm_fast
#endif

// ----------------------------------------------
// If desired, you can define uECC_WORD_SIZE as appropriate for your platform (4, or 8 bytes).
// If desired, you can define uECC_SUPPORTS_INT128 to indicate whether to use 128-bit variables.
// If uECC_WORD_SIZE and uECC_SUPPORTS_INT128 is not explicitly defined then it will be automatically set based on your platform.
// ----------------------------------------------
// #define uECC_WORD_SIZE  4
// #define uECC_SUPPORTS_INT128 0

// ----------------------------------------------
// Error type definition
// ----------------------------------------------
#define ECC_SUCCESS                   (ERR_ECC_BASE + 0)   // Success
#define ECC_ERR_PUB_EQUAL_ZERO       -(ERR_ECC_BASE + 1)   // Public key number is 0
#define ECC_ERR_PRI_EQUAL_ZERO       -(ERR_ECC_BASE + 2)   // Private key number is 0
#define ECC_ERR_RNG_UNSUITABLE       -(ERR_ECC_BASE + 3)   // Inappropriate random number
#define ECC_ERR_RNG_EQUAL_ZERO       -(ERR_ECC_BASE + 4)   // Random number is 0
#define ECC_ERR_RNG_NOT_GENERATE     -(ERR_ECC_BASE + 5)   // Unable to generate random number
#define ECC_ERR_SIG_EQUAL_ZERO       -(ERR_ECC_BASE + 6)   // The signature contains 0 (r=0 or s=0)
#define ECC_ERR_SIG_BIGGER_N         -(ERR_ECC_BASE + 7)   // Inappropriate signature  (r>n or s>n)
#define ECC_ERR_SHAREKEY_EQUAL_ZERO  -(ERR_ECC_BASE + 8)   // Shared key number is 0


#ifdef __cplusplus
extern "C"
{
#endif

/*
 The RNG function should fill p_size random bytes into p_dest. The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
 A correctly functioning RNG function must be set (using uECC_set_rng()) before calling uECC_make_key() or uECC_shared_secret().
 It should return value >= 0 if p_dest was filled with random data,
               or value <  0 if the random data could not be generated.
 */
typedef OhErrType (*uECC_RNG_Function)(OhUint8Type *p_dest, OhInt32Type p_size);

/*
 Set the function that will be used to generate random bytes.
 */
OhVoidType uECC_set_rng(uECC_RNG_Function p_rng);

/*
Generate an signature for a given hash value.
Inputs:
    p_privateKey - Your private key.
    p_hash       - The message hash to sign.
Outputs:
    p_signature  - Will be filled in with the signature value.
    Returns value >= 0 if the signature generated successfully, value < 0 if an error occurred.
*/
OhErrType uECC_sign(const OhUint8Type p_privateKey[uECC_BYTES], const OhUint8Type p_hash[uECC_BYTES], OhUint8Type p_signature[uECC_BYTES*2+1]);


#ifdef __cplusplus
}
#endif

#endif
